package com.talkweb.osmharmony.slice;

import com.talkweb.osmharmony.ResourceTable;
import com.talkweb.osmharmony.api.IMapController;
import com.talkweb.osmharmony.api.IMapView;
import com.talkweb.osmharmony.bean.InputTipsResult;
import com.talkweb.osmharmony.map.LocationHelper;
import com.talkweb.osmharmony.map.MapDataHelper;
import com.talkweb.osmharmony.map.MapManager;
import com.talkweb.osmharmony.provider.InputTipsProvider;
import com.talkweb.osmharmony.tileprovider.IRegisterReceiver;
import com.talkweb.osmharmony.tileprovider.modules.ArchiveFileFactory;
import com.talkweb.osmharmony.tileprovider.modules.IArchiveFile;
import com.talkweb.osmharmony.tileprovider.modules.OfflineTileProvider;
import com.talkweb.osmharmony.tileprovider.tilesource.FileBasedTileSource;
import com.talkweb.osmharmony.tileprovider.util.SimpleRegisterReceiver;
import com.talkweb.osmharmony.util.GeoPoint;
import com.talkweb.osmharmony.util.Log;
import com.talkweb.osmharmony.util.ResourceHelper;
import com.talkweb.osmharmony.utils.PermissionsUtils;
import com.talkweb.osmharmony.views.MapView;
import com.talkweb.osmharmony.views.overlay.ScaleBarOverlay;
import com.talkweb.osmharmony.views.overlay.compass.CompassOverlay;
import com.talkweb.osmharmony.views.overlay.compass.InternalCompassOrientationProvider;
import com.talkweb.osmharmony.views.overlay.gestures.RotationGestureOverlay;
import com.talkweb.osmharmony.views.overlay.mylocation.MyLocationNewOverlay;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.*;
import ohos.app.Environment;
import ohos.bundle.IBundleManager;
import ohos.media.image.PixelMap;
import ohos.security.SystemPermission;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class MainAbilitySlice extends AbilitySlice implements MapDataHelper.DataCallBack {

    private static final String TAG = "MainAbilitySlice";

    private MapView mapView;
    private IMapController mMapController;
    private DependentLayout mMapContainerView;
    private DependentLayout routeTipsLayout;
    private TextField startTextField;
    private TextField endTextField;
    private ListContainer listContainer;
    private DependentLayout inputTipsLayout;
    private DirectionalLayout navBottom;
    private Button btnStartNav;
    private Button btnEndNav;
    private String endLocation;
    private Button navTranslate;
    private DirectionalLayout selectPointLayout;
    private Text routeContent;
    private Image routeImage;

    private InputTipsProvider inputTipsProvider;
    private List<InputTipsResult.TipsEntity> tips = new ArrayList<>(0);
    private static final int INPUT_START = 1;
    private static final int INPUT_END = 2;
    private int inputType;
    private boolean isSetInputText = false;
    private MapDataHelper mapDataHelper;

    private MyLocationNewOverlay mLocationOverlay;
    private CompassOverlay mCompassOverlay;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        findView();
        initView();
        initMap();
        initInputTipsProvider();
        initListener();
    }

    private void initListener() {
        endTextField.setClickedListener(component -> inputTipsLayout.setVisibility(Component.VISIBLE));
        startTextField.setClickedListener(component -> inputTipsLayout.setVisibility(Component.VISIBLE));
        startTextField.addTextObserver((text, start, before, count) -> {
            if (!text.trim().isEmpty() && !isSetInputText) {
                mapDataHelper.getInputTips(text);
            }
        });

        endTextField.addTextObserver((text, start, before, count) -> {
            if (!text.trim().isEmpty() && !isSetInputText) {
                mapDataHelper.getInputTips(text);
            }
        });

        startTextField.setFocusChangedListener((component, hasFocus) -> {
            if (hasFocus) {
                inputType = INPUT_START;
            }
        });

        endTextField.setFocusChangedListener((component, hasFocus) -> {
            if (hasFocus) {
                inputType = INPUT_END;
            }
        });
    }

    private void findView() {
        mMapContainerView = (DependentLayout) findComponentById(ResourceTable.Id_osm_map_container);
        mapView = (MapView) findComponentById(ResourceTable.Id_osm_map_view);

        if (findComponentById(ResourceTable.Id_start_point_field) instanceof TextField) {
            startTextField = (TextField) findComponentById(ResourceTable.Id_start_point_field);
        }

        if (findComponentById(ResourceTable.Id_end_point_field) instanceof TextField) {
            endTextField = (TextField) findComponentById(ResourceTable.Id_end_point_field);
        }

        if (findComponentById(ResourceTable.Id_route_content) instanceof Text) {
            routeContent = (Text) findComponentById(ResourceTable.Id_route_content);
        }

        if (findComponentById(ResourceTable.Id_route_tips) instanceof DependentLayout) {
            routeTipsLayout = (DependentLayout) findComponentById(ResourceTable.Id_route_tips);
        }

        if (findComponentById(ResourceTable.Id_route_img) instanceof Image) {
            routeImage = (Image) findComponentById(ResourceTable.Id_route_img);
        }

        if (findComponentById(ResourceTable.Id_list_input_tips) instanceof ListContainer) {
            listContainer = (ListContainer) findComponentById(ResourceTable.Id_list_input_tips);
        }

        if (findComponentById(ResourceTable.Id_layout_input_tips) instanceof DependentLayout) {
            inputTipsLayout = (DependentLayout) findComponentById(ResourceTable.Id_layout_input_tips);
        }

        if (findComponentById(ResourceTable.Id_select_point) instanceof DirectionalLayout) {
            selectPointLayout = (DirectionalLayout) findComponentById(ResourceTable.Id_select_point);
        }

        if (findComponentById(ResourceTable.Id_nav_bottom) instanceof DirectionalLayout) {
            navBottom = (DirectionalLayout) findComponentById(ResourceTable.Id_nav_bottom);
        }

        if (findComponentById(ResourceTable.Id_start_nav) instanceof Button) {
            btnStartNav = (Button) findComponentById(ResourceTable.Id_start_nav);
        }

        if (findComponentById(ResourceTable.Id_end_nav) instanceof Button) {
            btnEndNav = (Button) findComponentById(ResourceTable.Id_end_nav);
        }

        if (findComponentById(ResourceTable.Id_nav_translate) instanceof Button) {
            navTranslate = (Button) findComponentById(ResourceTable.Id_nav_translate);
        }
    }

    private void initView() {
        // 解决ListContainer和NavMap的Touch事件冲突
        listContainer.setTouchEventListener((component, touchEvent) -> true);
        mapDataHelper = new MapDataHelper(mapView, this);
        mapDataHelper.setDataCallBack(this);
    }

    private void initMap() {
        //设置地图是可点击的
        mapView.setClickable(true);
        //显示地图下方的缩放按钮
        mapView.setBuiltInZoomControls(true);
        //设置地图支持多点触控操作
        mapView.setMultiTouchControls(true);
        //设置当前最大缩放级别
        mapView.setMaxZoomLevel(18.0);

        mMapController = mapView.getController();
        //设置初始化缩放级别
        mMapController.setZoom(15.0);
        //设置地图中心点位置
        mMapController.setCenter(new GeoPoint(28.222567, 112.884651));

        //指南针
        InternalCompassOrientationProvider compassProvider = new InternalCompassOrientationProvider(this);
        mCompassOverlay = new CompassOverlay(this, compassProvider, mapView);
        mCompassOverlay.setCompassInCenter(false);
        mCompassOverlay.setCompassCenter(30, 140);
        mapView.getOverlays().add(mCompassOverlay);

        //地图自由旋转
        RotationGestureOverlay mRotationGestureOverlay = new RotationGestureOverlay(mapView);
        mRotationGestureOverlay.setEnabled(true);
        mapView.getOverlays().add(mRotationGestureOverlay);

        //添加比例尺
        ScaleBarOverlay scaleBar = new ScaleBarOverlay(mapView);
        scaleBar.setAlignBottom(true); //底部显示
        scaleBar.setScaleBarOffset(30, 30);
        mapView.getOverlays().add(scaleBar);


        if (isGrantedLocationPermission()) {
            addMyLocationOverlayMark();
            getMyLocation();
        } else {
            PermissionsUtils.getInstance().setRequestListener(permission -> {
                if (permission.equals(SystemPermission.LOCATION)) {
                    Log.i(TAG, "onStart ====> permission: " + permission);
                    addMyLocationOverlayMark();
                    getMyLocation();
                }
            });
        }


        //加载离线地图
        File file = getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getParentFile();
        String strFilepath = file.getPath() + "/osmdroid/";
        Log.i(IMapView.LOGTAG, "offline file path: " + strFilepath);

        File[] files = new File(strFilepath).listFiles();
        if (files != null && files.length > 0) {
            File exitFile = files[0];
            if (exitFile.exists()) {
                String filename = exitFile.getName();
                String extension = filename.substring(filename.lastIndexOf(".") + 1);
                if (ArchiveFileFactory.isFileExtensionRegistered(extension)) {
                    IRegisterReceiver registerReceiver = new SimpleRegisterReceiver(this);
                    File[] offlineFiles = new File[]{exitFile};
                    OfflineTileProvider tileProvider = new OfflineTileProvider(registerReceiver, offlineFiles);
                    mapView.setTileProvider(tileProvider);

                    IArchiveFile[] archives = tileProvider.getArchives();
                    if (archives.length > 0) {
                        Set<String> tileSource = archives[0].getTileSources();
                        if (!tileSource.isEmpty()) {
                            String source = tileSource.iterator().next();
                            mapView.setTileSource(FileBasedTileSource.getSource(source));
                            mapView.setUseDataConnection(false);
                        }
                    }
                }
            }
        }

    }

    private boolean isGrantedLocationPermission() {
        return IBundleManager.PERMISSION_GRANTED
                == verifyCallingOrSelfPermission(SystemPermission.LOCATION);
    }

    private void addMyLocationOverlayMark() {
        //添加当前设备自动定位点，需要先具有设备位置权限
        mLocationOverlay = new MyLocationNewOverlay(mapView);
        PixelMap personPixelMap = ResourceHelper.getPixmap(this, ResourceTable.Media_person);
        PixelMap directionPixelMap = ResourceHelper.getPixmap(this, ResourceTable.Media_loc);
        mLocationOverlay.setDirectionArrow(personPixelMap, directionPixelMap);
        mapView.getOverlays().add(mLocationOverlay);
    }

    private void getMyLocation() {
        Log.i(TAG, "getMyLocation ====> request my location.");
        new LocationHelper().getMyLocation(this, loc -> {
            mapDataHelper.setLocation(loc.getLongitude() + "," + loc.getLatitude());
        });
    }

    private void initInputTipsProvider() {
        if (inputTipsProvider == null) {
            inputTipsProvider = new InputTipsProvider(this, tips);
            listContainer.setItemProvider(inputTipsProvider);
            listContainer.setItemClickedListener((container, component, position, id) -> {
                inputTipsLayout.setVisibility(Component.HIDE);
                if (inputType == INPUT_START) {
                    isSetInputText = true;
                    startTextField.setText(tips.get(position).getName());
                    isSetInputText = false;
                    String location = tips.get(position).getLocation();
                    String[] coordinates = location.split(",");
                    mapDataHelper.setMapCenter(Double.parseDouble(coordinates[0]), Double.parseDouble(coordinates[1]));
                    mapDataHelper.setLocation(location);
                } else {
                    endLocation = tips.get(position).getLocation();
                    isSetInputText = true;
                    endTextField.setText(tips.get(position).getName());
                    isSetInputText = false;
                }
                if (!startTextField.getText().trim().isEmpty() && !endTextField.getText().trim().isEmpty()) {
                    mapDataHelper.getRouteResult(endLocation);
                }
            });
        }
    }

    @Override
    public void onActive() {
        super.onActive();
        mapView.onResume();
        if (mLocationOverlay != null) {
            mLocationOverlay.enableMyLocation();
        }
        if (mCompassOverlay != null) {
            mCompassOverlay.enableCompass();
        }
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        mapView.onPause();
        if (mLocationOverlay != null) {
            mLocationOverlay.disableMyLocation();
        }
        if (mCompassOverlay != null) {
            mCompassOverlay.disableCompass();
        }
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    public void setInputTipsView(List<InputTipsResult.TipsEntity> inputTips) {
        tips.clear();
        tips.addAll(inputTips);
        MapManager.clearEmptyLocation(tips);
        inputTipsProvider.notifyDataChanged();
    }

    @Override
    public void setRouteView(String route) {
        Log.i(TAG, route);
        mapDataHelper.parseRoute(route);
    }
}
